From edb9f10aadbddd8a6d7ad652b02a5d9fa9227b6d Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Thu, 29 Mar 2007 15:47:49 +0000 Subject: [PATCH] Don't close menus on clicks on their border area (bug #423761). (modified 2007-03-29 Michael Natterer Don't close menus on clicks on their border area (bug #423761). (modified patch from maemo-gtk). * gtk/gtkmenu.c (gtk_menu_button_press) (gtk_menu_button_release): bail out early if the click was on the menu's border (not on any item and not outside the window). (pointer_in_menu_window): new utility function which checks if passed root coords are inside the menu_shell or one of its parent shells. svn path=/trunk/; revision=17571 --- ChangeLog | 13 +++++++++++++ gtk/gtkmenu.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 136981d8cf..cd0da1c29a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-03-29 Michael Natterer + + Don't close menus on clicks on their border area (bug #423761). + (modified patch from maemo-gtk). + + * gtk/gtkmenu.c (gtk_menu_button_press) + (gtk_menu_button_release): bail out early if the click was on the + menu's border (not on any item and not outside the window). + + (pointer_in_menu_window): new utility function which checks if + passed root coords are inside the menu_shell or one of its + parent shells. + 2007-03-29 Michael Natterer * gtk/gtkmenu.c: get rid of local GtkSettings variables by moving diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 93214ac438..92eb569bd7 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -2578,6 +2578,34 @@ gtk_menu_button_scroll (GtkMenu *menu, return FALSE; } +static gboolean +pointer_in_menu_window (GtkWidget *widget, + gdouble x_root, + gdouble y_root) +{ + GtkMenu *menu = GTK_MENU (widget); + + if (GTK_WIDGET_MAPPED (menu->toplevel)) + { + GtkMenuShell *menu_shell; + gint window_x, window_y; + + gdk_window_get_position (menu->toplevel->window, &window_x, &window_y); + + if (x_root >= window_x && x_root < window_x + widget->allocation.width && + y_root >= window_y && y_root < window_y + widget->allocation.height) + return TRUE; + + menu_shell = GTK_MENU_SHELL (widget); + + if (GTK_IS_MENU (menu_shell->parent_menu_shell)) + return pointer_in_menu_window (menu_shell->parent_menu_shell, + x_root, y_root); + } + + return FALSE; +} + static gboolean gtk_menu_button_press (GtkWidget *widget, GdkEventButton *event) @@ -2585,11 +2613,22 @@ gtk_menu_button_press (GtkWidget *widget, if (event->type != GDK_BUTTON_PRESS) return FALSE; - /* Don't pop down the menu for presses over scroll arrows + /* Don't pass down to menu shell for presses over scroll arrows */ if (gtk_menu_button_scroll (GTK_MENU (widget), event)) return TRUE; + /* Don't pass down to menu shell if a non-menuitem part of the menu + * was clicked. The check for the event_widget being a GtkMenuShell + * works because we have the pointer grabbed on menu_shell->window + * with owner_events=TRUE, so all events that are either outside + * the menu or on its border are delivered relative to + * menu_shell->window. + */ + if (GTK_IS_MENU_SHELL (gtk_get_event_widget ((GdkEvent *) event)) && + pointer_in_menu_window (widget, event->x_root, event->y_root)) + return TRUE; + return GTK_WIDGET_CLASS (gtk_menu_parent_class)->button_press_event (widget, event); } @@ -2608,11 +2647,18 @@ gtk_menu_button_release (GtkWidget *widget, if (event->type != GDK_BUTTON_RELEASE) return FALSE; - /* Don't pop down the menu for releases over scroll arrows + /* Don't pass down to menu shell for releases over scroll arrows */ if (gtk_menu_button_scroll (GTK_MENU (widget), event)) return TRUE; + /* Don't pass down to menu shell if a non-menuitem part of the menu + * was clicked (see comment in button_press()). + */ + if (GTK_IS_MENU_SHELL (gtk_get_event_widget ((GdkEvent *) event)) && + pointer_in_menu_window (widget, event->x_root, event->y_root)) + return TRUE; + return GTK_WIDGET_CLASS (gtk_menu_parent_class)->button_release_event (widget, event); } -- 2.30.2